﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;

namespace Urb.Weather.Core.Util
{
    public static class EqualityChecker
    {
        public static bool AreObjectsEqual<T>(T instance1, T instance2, params string[] ignoredPropertyNames)
	    {
	        Type type = typeof(T);
	        PropertyInfo[] properties = type.GetProperties();

            List<string> ignoredNames = new List<string>();

            if (ignoredPropertyNames != null)
                ignoredNames.AddRange(ignoredPropertyNames);
	 
	        foreach (PropertyInfo property in properties)
	        {
                if (!property.CanRead)
                    continue;

                if (ignoredNames.Contains(property.Name))
                    continue;

	            object valx = property.GetValue(instance1, null);
	            object valy = property.GetValue(instance2, null);

                if (valx == null || valy == null)
                {
                    if (valx != null || valy != null)
                        return false;
                }
                else
                {
                    if (!valx.Equals(valy))
                        return false;
                }
	        }
	 
	        return true;
	    }

        public static bool AreCollectionsEqual<T>(ICollection<T> collection1, ICollection<T> collection2)
        {
            if (collection1 == null)
            {
                if (collection2 == null)
                    return true;
                else
                    return false;
            }

            if (collection2 == null)
                return false;

            if (ICollection<T>.ReferenceEquals(collection1, collection2))
                return true;

            if (collection1.Count != collection2.Count)
                return false;

            List<T> expectedList = new List<T>(collection1);
            List<T> actualList = new List<T>(collection2);

            for (int i = 0; i < expectedList.Count; i++)
            {
                T expectedData = expectedList[i];
                T actualData = actualList[i];

                if (!EqualityChecker.AreObjectsEqual<T>(expectedData, actualData))
                    return false;
            }

            return true;
        }

        public static bool AreAllFieldsNotNull<T>(T instance, params string[] ignoredPropertyNames)
        {
            Type type = typeof(T);
            PropertyInfo[] properties = type.GetProperties();

            List<string> ignoredNames = new List<string>();

            if (ignoredPropertyNames != null)
                ignoredNames.AddRange(ignoredPropertyNames);

            foreach (PropertyInfo property in properties)
            {
                if (!property.CanRead)
                    continue;

                if (ignoredNames.Contains(property.Name))
                    continue;

                object valx = property.GetValue(instance, null);

                if (valx == null)
                    return false;
            }

            return true;
        }

        public static bool AreAllCollectionElementFieldsNotNull<T>(ICollection<T> collection)
        {
            if (collection == null || collection.Count <= 0)
                return true;

            foreach (T element in collection)
            {
                if (!AreAllFieldsNotNull<T>(element))
                    return false;
            }

            return true;
        }
    }
}
